<template>
    <el-select 
    v-bind:value="value" 
    v-bind="$attrs" 
    v-el-select-loadmore="loadMore(maxNum)" 
    v-on="$listeners"
    :placeholder="$attrs.placeholder" 
    :filter-method="handleFilter" 
    @visible-change="visibleChange"
    @focus="clearSelect('focus')" 
    @clear="clearSelect('clear')" 
    filterable 
    clearable 
    size="small">
        <el-option v-for="(item, index) in optionsList.slice(firstNum, maxNum)" 
        :key="item[props111.value] + index"
        v-bind="$attrs" 
        :label="item[props111.label]+ index" 
        :value="item[props111.value]" 
        @click.native="optionClick(item)">
        </el-option>
    </el-select>
</template>
  
<script>
//import PinyinMatch from "pinyin-match";
import { throttle } from "@/utils/tools"; // 封装的函数节流
export default {
    name: "SearchSelect",
    model: {
        prop: "value",
        event: "input",
    },
    props: {
        // 需要绑定的值 等于 v-model
        value: {
            type: [String, Number, Array, Object],
            default: "",
        },
        // 需要循环的数组 必传
        options: {
            type: Array,
            default() {
                return [];
            },
            required: true,
        },
        // el-option参数 必传
        props111: {
            type: Object,
            default() {
                return {
                    value: "value",
                    label: "label",
                };
            },
            required: true,
        },
    },
    data() {
        return {
            // 从父组件options中传入的大数组
            optionsList: [],

            copyOptionsList: [],
            firstNum: 0,
            maxNum: 100,
        };
    },
    directives: {
        "el-select-loadmore": (el, binding, vnode) => {
            const DROPDOWN_DOM = el.querySelector(
                ".el-select-dropdown .el-select-dropdown__wrap"
            );
            if (DROPDOWN_DOM) {
                DROPDOWN_DOM.addEventListener(
                    "scroll",
                    throttle(function () {
                        // this.scrollTop - 1 是为了兼容部分浏览器
                        const condition =
                            this.scrollHeight - this.scrollTop -1<= this.clientHeight;
                        if (condition) {
                            binding.value();
                        }
                    }),
                    200
                );
            }
        },
    },
    watch: {
        // 监听赋值并copy一份
        options: {
            handler(val) {
                this.optionsList = val;
                this.copyOptionsList = JSON.parse(JSON.stringify(val));
                this.showValueMethod();
            },
            deep: true,
        },
        value: {
            handler(val) {
                this.showValueMethod();
            },
        },
    },
    created() {
        this.optionsList = this.options;
        //深拷贝一份给copyOptionsList
        this.copyOptionsList = JSON.parse(JSON.stringify(this.options));
        this.showValueMethod();
    },

    methods: {
        /**
         * @Description: 下拉框支持模糊搜索
         * @Author: JayShen
         * @param {*} val
         */
        handleFilter(val) {
            try {
                if (val) {
                    this.firstNum = 0;
                    this.maxNum = 100;
                    this.optionsList = this.copyOptionsList;
                    this.optionsList = this.optionsList.filter((item) =>
                        //PinyinMatch.match(item[this.props111.label], val)
                        item[this.props111.label].toLowerCase().includes(val.toLowerCase())
                    );
                } else {
                    this.optionsList = this.copyOptionsList;
                }
            } catch (error) {
                console.error("模糊音下拉框：", error);
            }
        },

        /**
         * @Description: clear、focus事件还原数组
         * @Author: JayShen
         * @param {*}
         */
        clearSelect(type) {
            if (type === "clear") {
                this.firstNum = 0;
                this.maxNum = 100;
            }
            this.optionsList = this.copyOptionsList;
        },

        /**
         * @Description: 滚动增加最大条数
         * @Author: JayShen
         * @param {*} n
         */
        loadMore(n) {
            return () => (this.maxNum += 5);
        },

        /**
         * @Description: 触发下拉框展示
         * @Author: JayShen
         * @param {*} flag
         */
        visibleChange(flag) {
            if (flag) {
                this.handleFilter();
            }
        },

        /**
         * @Description: 解决数据回显问题
         * @Author: JayShen
         * @param {*}
         */
        showValueMethod() {
            if (
                this.value &&
                this.optionsList &&
                this.optionsList.length > this.maxNum
            ) {
                for (let i = 0; i < this.optionsList.length; i++) {
                    if (this.optionsList[i][this.props111.value] === this.value) {
                        if (i > this.maxNum) {
                            // 如果value位于数组后面部分，就截取前面的值，增加体验感
                            if (this.optionsList.length < i + this.maxNum) {
                                this.firstNum = i - this.maxNum;
                            } else {
                                this.firstNum = i - 5;
                            }
                            this.maxNum = i + this.maxNum;
                        }
                        break;
                    }
                }
            }
        },

        /**
         * @Description: option点击事件
         * @Author: JayShen
         * @param {*} item 当前选中的参数
         */
        optionClick(item) {
            this.$emit("optionClick", item);
        },
    },
};

</script>